/*
 * PhotonRTOS础光实时操作系统 -- scheduel table 实现文件
 *
 * Copyright (C) 2022 国科础石(重庆)软件有限公司
 *
 * 作者: Lin Yang <s-yanglin@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <autosar/internal.h>

/***********************************************************************
 *
 * [SWS_Os_00401] ⌈时间表应至少有一个到期点。 ⌋ ( )
 *
 * [SWS_Os_00407] ⌈到期点应激活至少一项任务或设置至少一项事件。 ⌋ ( )
 *
 * [SWS_Os_00442] ⌈给定调度表上的每个到期点都应具有唯一的偏移量。 ⌋ ( )
 *
 * [SWS_Os_00443] ⌈初始偏移量应为零或在基础计数器的OsCounterMinCycle ~
 *  OsCounterMaxAllowedValue范围内。 ⌋ ( )
 *
 * [SWS_Os_00408] ⌈相邻到期点之间的延迟应在底层计数器的OsCounterMinCycle ~
 *  OsCounterMaxAllowedValue范围内。 ⌋ ( )
 *
 * [SWS_Os_00007] ⌈操作系统模块应允许同时处理多个调度表。 ⌋ ( SRS_Os_00098 )
 *
 * [SWS_Os_00410] ⌈操作系统应该能够在任何时间点的每个计数器中处理至少一
 * 个调度表⌋ ( )
 *
 * [SWS_Os_00411] ⌈操作系统模块应使用tick，以便计数器上的一个tick对应于调
 * 度表上的一个tick。 ⌋ ( )
 *
 * [SWS_Os_00427] ⌈如果调度表是单次的，操作系统模块应允许 0 ~
 *  OsCounterMaxAllowedValue之间的最终延迟 底层计数器。 ⌋ ( )
 *
 * [SWS_Os_00444] ⌈对于周期表，最后延迟的值应在基础计数器
 * OsCounterMinCycle~OsCounterMaxAllowedValue之内。 ⌋ ( )
 *
 * [SWS_Os_00510] ⌈操作系统模块应在任务和闹钟自动启动后的启动过程中执行
 * 调度表的自动启动。 ⌋ ( )
 *
 * [SWS_Os_00429] ⌈隐式同步的操作系统模块的调度表的持续时间应等于其关联
 * 的 OSEK OS 计数器的OsCounterMaxAllowedValue + 1 。 ⌋ ( )
 *
 * [SWS_Os_00430] ⌈操作系统模块应防止隐式同步的调度表以相对计数值启动。
 *  ⌋ ( )
 *
 * [SWS_Os_00431] ⌈明确同步的调度表的持续时间不应大于驱动计数器的模数。
 *  ⌋ ( )
 *
 * [SWS_Os_00436] ⌈到期点的(Offset – OsScheduleTableMaxShorten ) 的值应大于前一个
 * 到期点的(Offset + OsCounterMinCycle )。 ⌋ ( )
 *
 * [SWS_Os_00559] ⌈ OsScheduleTableMaxLengthen的值应小于调度表的持续时间。 ⌋ ( )
 *
 * [SWS_Os_00437] ⌈到期点的 ( OsScheduleTableMaxLengthen + delay_from_previous_EP )的值应
 * 小于底层计数器的OsCounterMaxAllowedValue 。 ⌋ ( )
 *
 * [SWS_Os_00438] ⌈调度表应定义一个精度界限，其值在 0 到持续时间的范围内
 * 。 ⌋ ( )
 *
 *********************************************************************/

VAR(OsExpiryPointType, AUTOMATIC)
	autosar_expiry_points[AUTOSAR_NR_EXPIRY_POINT];
VAR(OsScheduleTableType, AUTOMATIC)
	autosar_schedule_tables[AUTOSAR_NR_SCHEDULE_TABLE];
VAR(OsExpiryPointTaskType, AUTOMATIC)
	autosar_expiry_point_tasks[AUTOSAR_NR_EXPIRY_POINT_TASK];
VAR(OsExpiryPointEventType, AUTOMATIC)
	autosar_expiry_point_events[AUTOSAR_NR_EXPIRY_POINT_EVENT];

VAR(int8, AUTOMATIC) short_string_of_schdule_table_status[][32] = {
	"...STOPPED",
	"...NEXT",
	"...WAITING",
	"...RUNNING",
	"...RUNNING_AND_SYNCHRONOUS",
	"...UNKNOWN_STATUS"
};

FUNC(int8 *, OS_CODE) ScheduleTableStatus2String(
	VAR(ScheduleTableStatusType, AUTOMATIC) status)
{
	if(status >= __SCHEDULETABLE_MAX)
		return short_string_of_schdule_table_status[__SCHEDULETABLE_MAX];
    return short_string_of_schdule_table_status[status];
}

/* 将到期点添加到调度表的实际实现 */
FUNC(StatusType, OS_CODE) __add_expiry_point_to_schedule_table(
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref,
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID)
{
	VAR(StatusType, AUTOMATIC) status = E_OK;
	VAR(OsScheduleTableRefType, AUTOMATIC) schedbtl_ref
		= &(autosar_schedule_tables[ScheduleTableID]);
	VAR(OsListRefType, AUTOMATIC) curr
		= schedbtl_ref->expriypts.next;

	expiry_point_ref->schedule_tableID = ScheduleTableID;
	/**
	 * 添加到调度表的到期点按照偏移量排序
	 * [SWS_Os_00002]
	 * ⌈ 操作系统模块应按照增加偏移量的顺序
	 * 处理时间表上从初始到期点到最终到期点的每个到期点。 ⌋
	 * ( SRS_Os_00098 )
	 */
	while (curr != &(schedbtl_ref->expriypts) &&
		list_container(curr, OsExpiryPointType, list)->time < expiry_point_ref->time) {
		curr = curr->next;
	}
	if (curr != &(schedbtl_ref->expriypts) &&
		list_container(curr, OsExpiryPointType, list)->time == expiry_point_ref->time) {
		pr_warn("[SWS_Os_00442] ⌈给定调度表上的每个到期点都应具有唯一的偏移量。⌋\n");
		status = E_OS_LIMIT;
		goto out;
	}
	__list_insert(&(expiry_point_ref->list), curr->prev, curr);

out:
	return status;
}


/* 将一个调度表绑定到计数器的实现 */
FUNC(StatusType, OS_CODE) bind_schedule_table_to_counter(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(CounterType, AUTOMATIC) CounterID)
{
	VAR(StatusType, AUTOMATIC) status = E_OK;

#if defined(EXTENDED_STATUS)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 */
	if ((ScheduleTableID >= AUTOSAR_NR_SCHEDULE_TABLE)
		|| (CounterID >= AUTOSAR_NR_COUNTER)) {
		status = E_OS_ID;
		goto out;
	}

	/**
	 * 检查max_value是否大于等于period
	 */
	if (autosar_schedule_tables[ScheduleTableID].duration
		> autosar_counters[CounterID].max_value) {
		status = E_OS_VALUE;
		goto out;
	}

#endif

	autosar_schedule_tables[ScheduleTableID].counterID = CounterID;

out:
	return status;
}


/* 获取调度表的下一个到期点 */
FUNC(OsExpiryPointRefType, OS_CODE) __get_next_expiry_point(
	VAR(OsScheduleTableRefType, AUTOMATIC) schedule_table_ref)
{
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref = NULL_PTR;

	/* 调度表没有到期点 */
	if (list_is_empty(&(schedule_table_ref->expriypts))) {
		pr_warn("[SWS_Os_00401] ⌈时间表应至少有一个到期点。⌋\n");

	/* 如果调度表还没有开始，就获取第一个到期点 */
	} else if (schedule_table_ref->next_pt == NULL_PTR) {
		expiry_point_ref = list_container(schedule_table_ref->expriypts.next,
			OsExpiryPointType, list);

	/* 当前节点是最后一个节点 */
	} else if (schedule_table_ref->next_pt->list.next == &(schedule_table_ref->expriypts)) {
		/* 如果存在需要进入的下一调度表 */
		if (schedule_table_ref->next_schedtblID != NO_NEXT_SCHEDULE_TABLE) {
			/* 循环调度表也进入下一调度表 */
			if (schedule_table_ref->cycle != 0) {
				expiry_point_ref = NULL_PTR;
			}

		/** 如果调度表循环则进入第一个节点
		 * [SWS_Os_00194]
		 * ⌈在处理完最终到期点之后，如果调度表重复，
		 * 操作系统将在最终延迟加上初始偏移tick过去之后
		 * 处理下一个初始到期点。 ⌋ ( )
		 */
		} else if (schedule_table_ref->cycle != 0) {
			expiry_point_ref = list_container(schedule_table_ref->expriypts.next,
				OsExpiryPointType, list);

		/** 否则调度表结束
		 * [SWS_Os_00009]
		 * ⌈如果调度表是单次的，
		 * 操作系统模块会在处理完最后到期点后
		 * 停止调度表最后延迟tick的处理。 ⌋ ( )
		 */
		} else {
			expiry_point_ref = NULL_PTR;
		}

	/* 当前节点不是最后一个节点，则进入下一节点 */
	} else {
		expiry_point_ref = list_container(schedule_table_ref->next_pt->list.next,
			OsExpiryPointType, list);
	}

	return expiry_point_ref;
}


#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
/* 获取绝对值 */
LOCAL_INLINE FUNC(TickType, OS_CODE) __abs(
	VAR(int32, AUTOMATIC) deviation)
{
	return (TickType)(deviation >= 0 ? deviation : -deviation);
}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */


/* 获取调度表下一节点到下下节点的位移，已经同步调整的值 */
FUNC(TickType, OS_CODE) __offset_next_2_expiry_point(
	VAR(OsScheduleTableRefType, AUTOMATIC) schedule_table_ref)
{
#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	VAR(TickType, AUTOMATIC) tmp_tick = 0;
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */
	VAR(TickType, AUTOMATIC) offset = 0;
	VAR(OsExpiryPointRefType, AUTOMATIC) next_2_expiry_point_ref = NULL_PTR;

	/* 获取下下节点 */
	next_2_expiry_point_ref = __get_next_expiry_point(schedule_table_ref);
	/* 没有则下一节点后调度表结束 */
	if (next_2_expiry_point_ref == NULL) {
		offset = 0;
	/* 下下节点不是第一个节点，没有遇到循环调度表 */
	} else if (next_2_expiry_point_ref->time > schedule_table_ref->next_pt->time) {
		offset = next_2_expiry_point_ref->time - schedule_table_ref->next_pt->time;
	/* 遇到循环调度表，下下节点是第一个节点 */
	} else {
		offset = schedule_table_ref->duration + next_2_expiry_point_ref->time
			- schedule_table_ref->next_pt->time;
	}

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	/**
	 * [SWS_Os_00418]
	 * ⌈如果偏差小于或等于配置的OsScheduleTblExplicitPrecision阈值，
	 * 操作系统模块应将显式同步调度表的状态设置为“运行和同步”。
	 * ⌋ ( )
	 *
	 * [SWS_Os_00419]
	 * ⌈如果偏差大于配置的OsScheduleTblExplicitPrecision阈值，
	 * 操作系统模块应将显式同步调度表的状态设置为“运行”。 ⌋ ( )
	 */
	if (schedule_table_ref->sync == EXPLICIT_SYNC) {
		if (__abs(schedule_table_ref->deviation) > schedule_table_ref->precision) {
			schedule_table_ref->status = SCHEDULETABLE_RUNNING;
		} else {
			schedule_table_ref->status = SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS;
		}
	}

	/**
	 * [SWS_Os_00417]
	 * ⌈操作系统模块应在提供同步计数后开始同步显式同步的调度表，
	 * 并应继续调整到期点直到同步。 ⌋ ( )
	 *
	 * [SWS_Os_00420]
	 * ⌈如果偏差非零且下一个到期点可调整
	 * 且表位于同步计数器后面(TableTicksAheadOfSyncCounter <= T
	 * ableTicksBehindOfSyncCounter)
	 * 那么操作系统将设置下一个 EP 到过期延迟 - 从当前过期开始的
	 *  min(MaxShorten, Deviation) tick。 ⌋ ( )
	 *
	 * [SWS_Os_00421]
	 * ⌈如果偏差非零并且下一个到期点是可调整的
	 * 并且表在同步计数器之前(TableTicksAheadOfSyncCounter > Ta
	 * bleTicksBehindOfSyncCounter)
	 * 那么操作系统应该将下一个 EP 设置为从当前到期开始的延迟 +
	 *  min(MaxLengthen, Deviation) tick。 ⌋ ( )
	 */
	if ((schedule_table_ref->sync == EXPLICIT_SYNC)
		&& (schedule_table_ref->deviation != 0)) {
		/* 调整下一节点到下下节点的偏移量，来减小偏差，慢慢同步 */
		if (schedule_table_ref->deviation < 0) {
			tmp_tick = min((TickType)-schedule_table_ref->deviation,
				next_2_expiry_point_ref->max_shorten);
			offset -= tmp_tick;
			schedule_table_ref->deviation += tmp_tick;
		} else {
			tmp_tick = min((TickType)schedule_table_ref->deviation,
				next_2_expiry_point_ref->max_lengthen);
			offset += tmp_tick;
			schedule_table_ref->deviation -= tmp_tick;
		}
	}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */

	return offset;
}


/**
 * 调度表的回调函数，
 * 在此函数中处理到期表的事务并调用当前到期点的回调函数
 */
FUNC(void, OS_CODE) schedule_table_callback(
	VAR(OsWaiterRefType, AUTOMATIC) waiter_ref)
{
	VAR(uintptr_t, AUTOMATIC) flags;
	VAR(OsScheduleTableRefType, AUTOMATIC) schedule_table_ref
		= (OsScheduleTableRefType)(waiter_ref->param);
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref
		= schedule_table_ref->next_pt;

	smp_lock_irqsave(&(schedule_table_ref->lock), flags);

	/* 进入下一节点 */
	schedule_table_ref->next_pt = __get_next_expiry_point(schedule_table_ref);
	if (schedule_table_ref->next_pt == NULL) {
		/* 如果存在需要进入的下一调度表 */
		if (schedule_table_ref->next_schedtblID < NO_NEXT_SCHEDULE_TABLE) {
			/* 循环调度表也进入下一调度表 */
			/**
			 * [SWS_Os_00414]
			 * ⌈当请求调度表切换时，操作系统将继续处理当前调度
			 * 表上的到期点。
			 * 在最终到期点之后，在处理切换到的调度表之前，
			 * 将有一个当前调度表的最终延迟tick的延迟。
			 * 在新调度表中，初始到期点将在初始偏移后处理。 ⌋ (
			 *  )
			 *
			 * [SWS_Os_00505]
			 * ⌈如果在NextScheduleTable ()调用中调度表
			 *  <ScheduleTableID_From> 和 <ScheduleTableID_To>
			 * 的OsScheduleTblSyncStrategy是EXPLICIT
			 * 并且操作系统模块已经同步 <ScheduleTableID_From>，
			 * 则 NextScheduleTable()将在处理开始后继续同步
			 *  <ScheduleTableID_To >。 ⌋ ( )
			 */
#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
			if ((schedule_table_ref->sync == EXPLICIT_SYNC) &&
				(autosar_schedule_tables[schedule_table_ref->
					next_schedtblID].sync == EXPLICIT)) {
				autosar_schedule_tables[schedule_table_ref->next_schedtblID].sync =
					EXPLICIT_SYNC;
			}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */
			if (schedule_table_ref->cycle != 0) {
				__stop_schedule_table(expiry_point_ref->schedule_tableID);
			}
			__start_schedule_table_rel(schedule_table_ref->next_schedtblID,
				schedule_table_ref->duration - expiry_point_ref->time);
		/* 否则调度表结束 */
		} else {
			schedule_table_ref->status = SCHEDULETABLE_STOPPED;
		}
		goto unlock_out;
	}

	/* 设置下一节点到下下节点的偏移量为等待者的循环 */
	schedule_table_ref->waiter.cycle = __offset_next_2_expiry_point(schedule_table_ref);

unlock_out:
	smp_unlock_irqrestore(&(schedule_table_ref->lock), flags);

	if (expiry_point_ref != NULL) {
		expiry_point_callback(expiry_point_ref);
	}
}


/* 调度表的到期点的任务执行函数 */
FUNC(void, OS_CODE) expiry_point_callback(
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref)
{
	VAR(OsListRefType, AUTOMATIC) curr;
	VAR(OsExpiryPointTaskRefType, AUTOMATIC) task_ref = NULL;
	VAR(OsExpiryPointEventRefType, AUTOMATIC) event_ref = NULL;

	/**
	 * [SWS_Os_00412]
	 * ⌈操作系统模块应首先处理
	 * 到期点上的所有任务激活，然后设置事件。 ⌋ ( )
	 */
	list_for_each(curr, &(expiry_point_ref->tasks)) {
		task_ref = list_container(curr, OsExpiryPointTaskType, list);
		/* pr_debug(" \t\tActivate task %d ...\n", task_ref->taskID); */
#if defined(AUTOSAR_OS_APPLICATION)
		if (osek_tasks[task_ref->taskID].core_id == GetCoreID()) {
			ActivateTask(task_ref->taskID);
		} else {
			ActivateTaskAsyn(task_ref->taskID);
		}
#else /* defined(AUTOSAR_OS_APPLICATION) */
		ActivateTask(task_ref->taskID);
#endif /* defined(AUTOSAR_OS_APPLICATION) */
	}
	list_for_each(curr, &(expiry_point_ref->events)) {
		event_ref = list_container(curr, OsExpiryPointEventType, list);
		/* pr_debug(" \t\tSet event %x on task %d ...\n", event_ref->event,
		 *  event_ref->taskID); */
#if defined(AUTOSAR_OS_APPLICATION)
		if (osek_tasks[event_ref->taskID].core_id == GetCoreID()) {
			SetEvent(event_ref->taskID, event_ref->event);
		} else {
			SetEventAsyn(event_ref->taskID, event_ref->event);
		}
#else /* defined(AUTOSAR_OS_APPLICATION) */
		SetEvent(event_ref->taskID, event_ref->event);
#endif /* defined(AUTOSAR_OS_APPLICATION) */
	}
	if ((task_ref == NULL) && (event_ref == NULL)) {
		pr_warn("[SWS_Os_00407] ⌈到期点应激活至少一项任务或设置至少一项事件。⌋\n");
	}
}


/* 根据expiry_point指针获取expiry_point id，
 * 返回 AUTOSAR_NR_EXPIRY_POINT 表示指针无效 */
FUNC(OsExpiryPointIdType, OS_CODE) get_expiry_point_id(
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref)
{
	VAR(uintptr_t, AUTOMATIC) index = 0;

	index = (((uintptr_t)expiry_point_ref -
		(uintptr_t)autosar_expiry_points) / sizeof(OsExpiryPointType));
	if (index > AUTOSAR_NR_EXPIRY_POINT) {
		index = AUTOSAR_NR_EXPIRY_POINT;
	}

	return (OsWaiterIdType)index;
}

#include <autosar/internal.h>


/* 在绝对时刻开始调度表的实际实现 */
FUNC(void, OS_CODE) __start_schedule_table_abs(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(TickType, AUTOMATIC) Start)
{
	VAR(OsScheduleTableRefType, AUTOMATIC) schedule_table_ref
		= &(autosar_schedule_tables[ScheduleTableID]);
	VAR(OsExpiryPointRefType, AUTOMATIC) expiry_point_ref
		= list_container(schedule_table_ref->expriypts.next, OsExpiryPointType, list);
	VAR(TickType, AUTOMATIC) max_time
		= autosar_counters[schedule_table_ref->counterID].max_value;

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	switch (schedule_table_ref->sync) {
	case NO_SYNC:
	case EXPLICIT_ASYNC:
		schedule_table_ref->status = SCHEDULETABLE_RUNNING;
		break;
	case EXPLICIT_SYNC:
	case IMPLICIT_SYNC:
		schedule_table_ref->status = SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS;
		break;
	}
#else /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */
	schedule_table_ref->status = SCHEDULETABLE_RUNNING;
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */

	/* 将第一节点设为下一处理节点 */
	schedule_table_ref->next_pt = expiry_point_ref;
	/* 将调度表自己的指针设为等待者回调的数据 */
	schedule_table_ref->waiter.param = (P2VAR(void, AUTOMATIC, OS_APPL_DATA))schedule_table_ref;
	/* 将初始偏移量和绝对开始时间的和作为第一次回调的时间 */
	schedule_table_ref->waiter.time = Start + expiry_point_ref->time;
	if (schedule_table_ref->waiter.time > max_time) {
		schedule_table_ref->waiter.time -= (max_time + 1);
	}
	/* 设置调度表的回调函数 */
	schedule_table_ref->waiter.callback = schedule_table_callback;

	/* 设置下一节点到下下节点的偏移量为等待者的循环 */
	schedule_table_ref->waiter.cycle = __offset_next_2_expiry_point(schedule_table_ref);

	add_waiter_to_counter(&(schedule_table_ref->waiter), schedule_table_ref->counterID);
}

/*
 * 语法
 * StatusType StartScheduleTableAbs (
 *      ScheduleTableType ScheduleTableID,
 *      TickType Start
 * )
 *
 * 服务 ID [hex]
 *      0x08
 *
 * 同步/异步
 *      同步（Synchronous）
 *
 * 可重入性
 *      可重入
 *
 * 参数 (in)
 *      Schedule TableID
 *      待启动的调度表
 *      Start
 *      计划表开始时的绝对计数器刻度值
 *
 * 参数 (inout)
 *      None
 *
 * 参数 (out)
 *      None
 *
 * 返回值
 *      StatusType
 *      E_OK：无错误
 *      E_OS_ID（仅处于 EXTENDED 状态）：ScheduleTableID 无效
 *      E_OS_VALUE（仅处于 EXTENDED 状态）：“Start”的值比 OsCounterMaxAllowedValue
 * 更大
 *      E_OS_STATE：调度表已经启动了
 *
 * 描述
 *      该服务以基础计数器上的绝对值“Start”开始处理调度表。
 *
 * 引用
 *      AUTOSAR OS 8.4.10 StartScheduleTableAbs [SWS_Os_00358]
 */
FUNC(StatusType, OS_CODE) StartScheduleTableAbs(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(TickType, AUTOMATIC) Start)
{
	VAR(uintptr_t, AUTOMATIC) flags;
	VAR(StatusType, AUTOMATIC) status = E_OK;
	VAR(CounterType, AUTOMATIC) counter_id;

#if defined(AUTOSAR_OS_APPLICATION)
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();

	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
#endif /* defined(AUTOSAR_OS_APPLICATION) */

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)

#if defined(EXTENDED_STATUS)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 *
	 * [SWS_Os_00348]
	 * ⌈如果StartScheduleTableAbs()调用中的
	 * 调度表 <ScheduleTableID>无效，
	 * 则 StartScheduleTableAbs()应返回E_OS_ID 。 ⌋ ( )
	 */
	if (ScheduleTableID >= AUTOSAR_NR_SCHEDULE_TABLE) {
		status = E_OS_ID;
		goto out;
	}

#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(app_id, TYPE_SCHEDULE_TABLE,
		&autosar_schedule_tables[ScheduleTableID].object) != ACCESS) {
		status = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_OS_APPLICATION) */

	/**
	 * 检查调度表是否绑定了有效的计数器
	 * 注意：原需求规格中未要求
	 */
	counter_id = autosar_schedule_tables[ScheduleTableID].counterID;
	if (counter_id >= AUTOSAR_NR_COUNTER) {
		status = E_OS_VALUE;
		goto out;
	}

	/**
	 * 检查“Start”的值是否比 OsCounterMaxAllowedValue更大
	 *
	 * [SWS_Os_00349]
	 * ⌈如果StartScheduleTableAbs()调用中
	 * 的 <Start>大于底层计数器的OsCounterMaxAllowedValue ，
	 * 则StartScheduleTableAbs()应返回E_OS_VALUE 。 ⌋ ( )
	 */
	if (Start > autosar_counters[counter_id].max_value) {
		status = E_OS_VALUE;
		goto out;
	}
#endif

	/* 一定要先检查ID有效之后再上锁 */
	smp_lock_irqsave(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

	/************************************
	 * [SWS_Os_00522]
	 * ⌈ StartScheduleTableAbs()的可用性：
	 * 可用于所有可扩展性类。 ⌋ ( )
	 *************************************/

	/**
	 * [SWS_Os_00350]
	 * ⌈如果StartScheduleTableAbs()调用中的
	 * 调度表 <ScheduleTableID>不处于状态SCHEDULETABLE_STOPPED ，
	 * 则 StartScheduleTableAbs()应返回E_OS_STATE 。 ⌋ ( )
	 */
	if (autosar_schedule_tables[ScheduleTableID].status != SCHEDULETABLE_STOPPED) {
		status = E_OS_STATE;
		goto unlock_out;
	}

	/**
	 * [SWS_Os_00351]
	 * ⌈如果StartScheduleTableAbs()的输入参数有效
	 * 且 <ScheduleTableID> 处于状态SCHEDULETABLE_STOPPED ，
	 * 则 StartScheduleTableAbs()将在
	 * 底层计数器下一个等于 <Start> 时开始处理调度表 <ScheduleTableID>
	 *  并设置<ScheduleTableID> 的状态为
	 *
	 * SCHEDULETABLE_RUNNING （用于非同步/显式同步的调度表）或
	 * SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS （用于隐式同步的调度表）
	 *
	 * 在返回给用户之前。
	 * （当底层计数器下一个等于 <Start>+Initial Offset 时，
	 * 将处理初始到期点）。 ⌋ ( )
	 */
	__start_schedule_table_abs(ScheduleTableID, Start);

unlock_out:
	smp_unlock_irqrestore(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

out:
	return status;
}

/* 在相对时刻开始调度表的实际实现 */
FUNC(StatusType, OS_CODE) __start_schedule_table_rel(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(TickType, AUTOMATIC) Offset)
{
	VAR(TickType, AUTOMATIC) now = 0;
	VAR(StatusType, AUTOMATIC) status = E_OK;
	VAR(CounterType, AUTOMATIC) counter_id
		= autosar_schedule_tables[ScheduleTableID].counterID;

	status = GetCounterValue(counter_id, &now);
	if (status != E_OK) {
		goto out;
	}
	__start_schedule_table_abs(ScheduleTableID, now + Offset);

out:
	return status;
}

/**
 * 语法
 * StatusType StartScheduleTableRel (
 *      ScheduleTableType ScheduleTableID,
 *      TickType Offset
 * )
 *
 * 服务 ID [hex]
 *      0x07
 *
 * 同步/异步
 *      同步（Synchronous）
 *
 * 可重入性
 *      可重入
 *
 * 参数 (in)
 *      Schedule TableID
 *      待启动的调度表
 *
 * Offset
 *      在调度表处理开始之前计数器上的tick数
 *
 * 参数 (inout)
 *      None
 *
 * 参数 (out)
 *      None
 *
 * 返回值
 *      StatusType
 *      E_OK：无错误
 *      E_OS_ID（仅处于 EXTENDED 状态）：ScheduleTableID 无效。
 *      E_OS_VALUE（仅在 EXTENDED 状态下）：偏移量大于
 *		        （OsCounterMaxAllowedValue - InitialOffset）或等于 0。
 *      E_OS_STATE：调度表已经启动。
 *
 * 描述
 *      此服务在相对于基础计数器上的“Now”值的“Offset”处开始处理调度
 * 表。
 *
 * 引用：
 *      AUTOSAR OS 8.4.9 StartScheduleTableRel [SWS_Os_00347]
 */
FUNC(StatusType, OS_CODE) StartScheduleTableRel(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(TickType, AUTOMATIC) Offset)
{
	VAR(uintptr_t, AUTOMATIC) flags;
	VAR(StatusType, AUTOMATIC) status = E_OK;
	VAR(CounterType, AUTOMATIC) counter_id;
	VAR(OsExpiryPointRefType, AUTOMATIC) first_expiry_point_ref;

#if defined(AUTOSAR_OS_APPLICATION)
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();
#endif

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)
	
#if defined(AUTOSAR_OS_APPLICATION)
	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(EXTENDED_STATUS)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 *
	 * [SWS_Os_00275]
	 * ⌈如果StartScheduleTableRel()调用中的
	 * 调度表 <ScheduleTableID>无效，
	 * 则 StartScheduleTableRel()应返回E_OS_ID 。 ⌋ ( )
	 */
	if (ScheduleTableID >= AUTOSAR_NR_SCHEDULE_TABLE) {
		status = E_OS_ID;
		goto out;
	}

#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(app_id, TYPE_SCHEDULE_TABLE,
		&autosar_schedule_tables[ScheduleTableID].object) != ACCESS) {
		status = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	/**
	 * [SWS_Os_00452]
	 * ⌈如果调度表 <ScheduleTableID> 在
	 * StartScheduleTableRel()的调用中是隐式同步的
	 * （ OsScheduleTblSyncStrategy   = IMPLICIT )，
	 * 则 StartScheduleTableRel()应返回E_OS_ID 。 ⌋ ( )
	 */
	if (autosar_schedule_tables[ScheduleTableID].sync == IMPLICIT_SYNC) {
		status = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */

	/**
	 * [SWS_Os_00332]
	 * ⌈如果StartScheduleTableRel()调用中的 <Offset>为零，
	 * 则StartScheduleTableRel()应返回E_OS_VALUE 。 ⌋ ( )
	 */
	if (Offset == 0) {
		status = E_OS_VALUE;
		goto out;
	}

	/**
	 * 检查调度表是否绑定了有效的计数器
	 * 注意：原需求规格中未要求
	 */
	counter_id = autosar_schedule_tables[ScheduleTableID].counterID;
	if (counter_id >= AUTOSAR_NR_COUNTER) {
		status = E_OS_VALUE;
		goto out;
	}

	/**
	 * [SWS_Os_00276]
	 * ⌈如果偏移量 <Offset> )
	 * 大于底层计数器的OsCounterMaxAllowedValue减去初始偏移量，
	 * StartScheduleTableRel()应返回E_OS_VALUE 。 ⌋ ( )
	 */
	first_expiry_point_ref =
		list_container(autosar_schedule_tables[ScheduleTableID].expriypts.next,
		OsExpiryPointType, list);
	if (Offset > (autosar_counters[counter_id].max_value - first_expiry_point_ref->time)) {
		status = E_OS_VALUE;
		goto out;
	}
#endif

	/* 一定要先检查ID有效之后再上锁 */
	smp_lock_irqsave(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

	/*************************************
	 * [SWS_Os_00521]
	 * ⌈ StartScheduleTableRel()的可用性：
	 * 可用于所有可伸缩性类。 ⌋ ( )
	 **************************************/

	/**
	 * [SWS_Os_00277]
	 * ⌈如果StartScheduleTableRel()调用中的
	 * 调度表 <ScheduleTableID>不处于
	 * 状态SCHEDULETABLE_STOPPED ，
	 * 则 StartScheduleTableRel()应返回E_OS_STATE 。 ⌋ ( )
	 */
	if (autosar_schedule_tables[ScheduleTableID].status != SCHEDULETABLE_STOPPED) {
		status = E_OS_STATE;
		goto unlock_out;
	}

	/**
	 * [SWS_Os_00278]
	 * ⌈如果StartScheduleTableRel()的输入参数有效
	 * 且调度表 <ScheduleTableID> 的状态为SCHEDULETABLE_STOPPED ，
	 * 则StartScheduleTableRel()应开始处理调度表 <ScheduleTableID>。
	 * 初始到期点应在基础计数器上经过
	 *  <Offset> + Initial Offset 刻度后处理。
	 *  <ScheduleTableID> 的状态在服务返回给调用者
	 * 之前设置为SCHEDULETABLE_RUNNING 。 ⌋ ( )
	 */
	status = __start_schedule_table_rel(ScheduleTableID, Offset);

unlock_out:
	smp_unlock_irqrestore(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

out:
	return status;
}



#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
/*
 * 语法
 * StatusType StartScheduleTableSynchron (
 *      ScheduleTableType ScheduleTableID
 * )
 *
 * 服务 ID [hex]
 *      0x0b
 *
 * 同步/异步
 *      同步（Synchronous）
 *
 * 可重入性
 *      可重入
 *
 * 参数 (in)
 *      ScheduleTableID
 *      计划表开始
 *
 * 参数 (inout)
 *      None
 *
 * 参数 (out)
 *      None
 *
 * 返回值
 *      StatusType
 *      E_OK：无错误
 *      E_OS_ID（仅处于 EXTENDED 状态）：ScheduleTableID 无效
 *      E_OS_STATE：调度表已经启动
 *
 * 描述
 *      此服务同步启动显式同步的调度表。
 *
 * 引用
 *      AUTOSAR OS 8.4.13 StartScheduleTableSynchron [SWS_Os_00201]
 */
FUNC(StatusType, OS_CODE) StartScheduleTableSynchron(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID)
{
	VAR(uintptr_t, AUTOMATIC) flags;
	VAR(StatusType, AUTOMATIC) status = E_OK;

#if defined(AUTOSAR_OS_APPLICATION)
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();

	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
#endif /* defined(AUTOSAR_OS_APPLICATION) */

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR | ENV_ERROR_HOOK)

#if defined(EXTENDED_STATUS)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 *
	 * [SWS_Os_00387]
	 * ⌈如果在调用StartScheduleTableSynchron()
	 * 时调度表 <ScheduleTableID> 无效
	 * 或调度表 <ScheduleTableID> 未显式同步
	 *  ( OsScheduleTblSyncStrategy ! = EXPLICIT)
	 * StartScheduleTableSynchron()应返回E_OS_ID 。 ⌋ ( )
	 */
	if ((ScheduleTableID >= AUTOSAR_NR_SCHEDULE_TABLE)
		|| ((autosar_schedule_tables[ScheduleTableID].sync & EXPLICIT) != EXPLICIT)) {
		status = E_OS_ID;
		goto out;
	}

#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(app_id, TYPE_SCHEDULE_TABLE,
		&autosar_schedule_tables[ScheduleTableID].object) != ACCESS) {
		status = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_OS_APPLICATION) */
#endif

	/* 一定要先检查ID有效之后再上锁 */
	smp_lock_irqsave(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

	/********************************************
	 * [SWS_Os_00525]
	 * ⌈ StartScheduleTableSynchron()的可用性：
	 * 在可扩展性类 2 和 4 中可用。⌋ ( )
	 ********************************************/

	/**
	 * [SWS_Os_00388]
	 * ⌈如果StartScheduleTableSynchron()调用中的
	 * 调度表 <ScheduleTableID>不处于状态SCHEDULETABLE_STOPPED ，
	 * 则 StartScheduleTableSynchron()应返回E_OS_STATE 。 ⌋ ( )
	 */
	if (autosar_schedule_tables[ScheduleTableID].status != SCHEDULETABLE_STOPPED) {
		status = E_OS_STATE;
		goto unlock_out;
	}

	/**
	 * [SWS_Os_00389]
	 * ⌈如果<ScheduleTableID> 在StartScheduleTableSynchron()调用时有效，
	 * StartScheduleTableSynchron()应设置<ScheduleTableID> 的
	 * 状态为SCHEDULETABLE_WAITING
	 * 并在通过SyncScheduleTable()设置调度表的同步计数后
	 * 开始处理调度表<ScheduleTableID> 。
	 * 当同步计数器上的 (Duration-SyncValue)+InitialOffset tick已经过去时，
	 * 应处理初始到期点，其中：
	 * 持续时间是 <ScheduleTableID>.OsScheduleTableDurationSyncValue
	 * 是传递给SyncScheduleTable()的 <Value> 参数
	 * InitialOffset是 <ScheduleTableID> 中最短的过期点偏移量 ⌋ ( )
	 *
	 * [SWS_Os_00435]
	 * ⌈如果显式同步的调度表是同步启动的，
	 * 则操作系统模块应保证在服务StartScheduleTableSynchron()
	 * 调用返回时它处于“等待”状态。 ⌋ ( )
	 */
	autosar_schedule_tables[ScheduleTableID].status = SCHEDULETABLE_WAITING;

unlock_out:
	smp_unlock_irqrestore(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

out:
	return status;
}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */


/* 暂停调度表的实际实现 */
FUNC(StatusType, OS_CODE) __stop_schedule_table(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID)
{
	VAR(StatusType, AUTOMATIC) status = E_OK;
	VAR(OsScheduleTableRefType, AUTOMATIC) schedule_table_ref
		= &(autosar_schedule_tables[ScheduleTableID]);

	/**
	 * 停止后不需要保留数据，因为不需要继续运行
	 * [SWS_Os_00428]
	 * ⌈如果调度表处理在到达最终到期点之前被取消并随后重新启动，
	 * 则SWS_Os_00358 / SWS_Os_00347意味着重新启动从调度表的开始发生。 ⌋ ( )
	 */
	status = remove_waiter_from_counter(&(schedule_table_ref->waiter),
		schedule_table_ref->counterID);
	schedule_table_ref->status = SCHEDULETABLE_STOPPED;
	schedule_table_ref->next_pt = NULL_PTR;

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	if (schedule_table_ref->sync == EXPLICIT_SYNC) {
		schedule_table_ref->sync = EXPLICIT;
	}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */

	return status;
}

/*
 * 语法
 * StatusType StopScheduleTable (
 *      ScheduleTableType ScheduleTableID
 * )
 *
 * 服务 ID [hex]
 *      0x09
 *
 * 同步/异步
 *      同步（Synchronous）
 *
 * 可重入性
 *      可重入
 *
 * 参数 (in)
 *      ScheduleTableID
 *      要停止的调度表
 *
 * 参数 (inout)
 *      None
 *
 * 参数 (out)
 *      None
 *
 * 返回值
 *      StatusType
 *      E_OK：无错误
 *      E_OS_ID（仅处于 EXTENDED 状态）：ScheduleTableID 无效。
 *      E_OS_NOFUNC：调度表已经停止
 *
 * 描述
 *      此服务会在调度表运行期间的任何时候立即取消对调度表的处理。
 *
 * 引用
 *      AUTOSAR OS 8.4.11 StopScheduleTable [SWS_Os_00006]
 */
FUNC(StatusType, OS_CODE) StopScheduleTable(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID)
{
	VAR(uintptr_t, AUTOMATIC) flags;
	VAR(StatusType, AUTOMATIC) status = E_OK;

#if defined(AUTOSAR_OS_APPLICATION)
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();
#endif

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)

#if defined(AUTOSAR_OS_APPLICATION)
	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(EXTENDED_STATUS)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 *
	 * [SWS_Os_00279]
	 * ⌈如果调度表标识符 <ScheduleTableID> 在
	 * 调用StopScheduleTable()无效，
	 * 则 StopScheduleTable()应返回E_OS_ID 。 ⌋ ( )
	 */
	if (ScheduleTableID >= AUTOSAR_NR_SCHEDULE_TABLE) {
		status = E_OS_ID;
		goto out;
	}

#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(app_id, TYPE_SCHEDULE_TABLE,
		&autosar_schedule_tables[ScheduleTableID].object) != ACCESS) {
		status = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_OS_APPLICATION) */
#endif

	/* 一定要先检查ID有效之后再上锁 */
	smp_lock_irqsave(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

	/**************************************
	 * [SWS_Os_00523]
	 * ⌈ StopScheduleTable()的可用性：
	 * 可用于所有可扩展性类。 ⌋ ( )
	 ***************************************/

	/**
	 * [SWS_Os_00280]
	 * ⌈如果在调用	StopScheduleTable()时
	 * 标识符为 <ScheduleTableID> 的调度表
	 * 处于SCHEDULETABLE_STOPPED状态，
	 * 则 StopScheduleTable()应返回E_OS_NOFUNC 。 ⌋ ( )
	 */
	if (autosar_schedule_tables[ScheduleTableID].status == SCHEDULETABLE_STOPPED) {
		status = E_OS_NOFUNC;
		goto unlock_out;
	}

	/**
	 * [SWS_Os_00281]
	 * ⌈如果StopScheduleTable()的输入参数有效，
	 * StopScheduleTable()应将 <ScheduleTableID> 的
	 * 状态设置为SCHEDULETABLE_STOPPED并且
	 * （停止调度表 <ScheduleTableID> 处理任何进一步的到期点并且）
	 * 应返回E_OK 。 ⌋ ( )
	 */
	status = __stop_schedule_table(ScheduleTableID);

	/**
	 * 需求来源于 <NextScheduleTable.c> 文件
	 * [SWS_Os_00453]
	 * ⌈如果NextScheduleTable()调用中的
	 * < ScheduleTableID_From>停止，
	 * 则 NextScheduleTable()不应启动“下一个”调度表
	 * 并将其状态更改为SCHEDULETABLE_STOPPED 。 ⌋ ( )
	 */
	if (autosar_schedule_tables[ScheduleTableID].next_schedtblID != NO_NEXT_SCHEDULE_TABLE) {
		autosar_schedule_tables[autosar_schedule_tables[ScheduleTableID].next_schedtblID].status =
		    SCHEDULETABLE_STOPPED;
		autosar_schedule_tables[ScheduleTableID].next_schedtblID = NO_NEXT_SCHEDULE_TABLE;
	}

unlock_out:
	smp_unlock_irqrestore(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

out:
	return status;
}

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
LOCAL_INLINE FUNC(StatusType, OS_CODE) __sync_schedule_table(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(TickType, AUTOMATIC) Value)
{
	VAR(TickType, AUTOMATIC) counter_value = 0;
	VAR(TickType, AUTOMATIC) position_on_tbl = 0;
	VAR(StatusType, AUTOMATIC) status = E_OK;
	VAR(OsScheduleTableRefType, AUTOMATIC) schedule_table_ref
		= &(autosar_schedule_tables[ScheduleTableID]);

	/**
	 * [SWS_Os_00417]
	 * ⌈操作系统模块应在提供同步计数后开始同步显式同步的调度表，
	 * 并应继续调整到期点直到同步。 ⌋ ( )
	 */
	autosar_schedule_tables[ScheduleTableID].sync = EXPLICIT_SYNC;

	/* 如果才开始启动同步调度表，直接同步启动 */
	if (schedule_table_ref->status == SCHEDULETABLE_WAITING) {
		status = __start_schedule_table_rel(ScheduleTableID,
			schedule_table_ref->duration - Value);

	/** 如果同步调度表已启动，需要同步
	 * [SWS_Os_00013]
	 * ⌈操作系统模块应提供将调度表的处理
	 * 与已知计数器值同步的能力。 ⌋ ( SRS_Os_11002 )
	 */
	} else {
		/* 获取驱动计数器的当前值 */
		status = GetCounterValue(schedule_table_ref->counterID, &counter_value);
		if (status != E_OK) {
			goto out;
		}

		/** 计算调度表当前位置和与同步值的偏差
		 * [SWS_Os_00206]
		 * ⌈当提供新的同步计数时，
		 * 操作系统模块应计算显式同步的调度表
		 * 与同步计数之间的当前偏差。 ⌋
		 * ( SRS_Os_11002 )
		 */
		/* 允许数据溢出，两次溢出后达到负数的效果
			* 最后一个节点后，调度表结束前，position_on_tbl为负数，
			* 同步会导致调度表在下一轮循环中同步，
			* 下面的调整可能导致变化 */
	position_on_tbl =
		schedule_table_ref->next_pt->time - (schedule_table_ref->
			waiter.time - counter_value);
		schedule_table_ref->deviation = position_on_tbl - Value;
		/* 计算最近的同步点，由于每个到期点
			* 前后可调整不一样，所以不一定是最快同步点
			*/
		if (schedule_table_ref->deviation > (int32)schedule_table_ref->duration / 2) {
			schedule_table_ref->deviation -= (int32)schedule_table_ref->duration;
		} else if (schedule_table_ref->deviation < -(int32)schedule_table_ref->duration / 2) {
			schedule_table_ref->deviation += (int32)schedule_table_ref->duration;
		} else {
			;
		}

		/* 设置下一节点到下下节点的偏移量为等待者的循环 */
		schedule_table_ref->waiter.cycle = __offset_next_2_expiry_point(schedule_table_ref);
	}

out:
	return status;
}

/*
* 语法
* StatusType SyncScheduleTable (
*      ScheduleTableType ScheduleTableID,
*      TickType Value
* )
*
* 服务 ID [hex]
*      0x0c
*
* 同步/异步
*      同步（Synchronous）
*
* 可重入性
*      可重入
*
* 参数 (in)
*      ScheduleTableID
*      要同步的调度表
*
*      Value
*      同步计数器的当前值
*
* 参数 (inout)
*      None
*
* 参数 (out)
*      None
*
* 返回值
*      StatusType
*      E_OK：没有错误
*      E_OS_ID（仅处于 EXTENDED 状态）：ScheduleTableID 无效或调度
*      表无法同步（未设置 OsScheduleTblSyncStrategy 或
*      OsScheduleTblSyncStrategy = 隐式（IMPLICIT））
*      E_OS_VALUE（仅处于 EXETENDED 状态）：<Value> 超出范围
*      E_OS_STATE：调度表<ScheduleTableID>的状态等于
*      SCHEDULETABLE_STOPPED
*
* 描述
*      该服务为调度表提供同步计数和开始同步。
*
* 引用
*      AUTOSAR OS 8.4.14 SyncScheduleTable [SWS_Os_00199]
*/
FUNC(StatusType, OS_CODE) SyncScheduleTable(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(TickType, AUTOMATIC) Value)
{
	VAR(uintptr_t, AUTOMATIC) flags;
	VAR(StatusType, AUTOMATIC) status = E_OK;

#if defined(AUTOSAR_OS_APPLICATION)
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();

	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
#endif /* defined(AUTOSAR_OS_APPLICATION) */

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)

#if defined(EXTENDED_STATUS)

	/**
	 * 在扩展模式下，检查传入参数是否过大
	 *
	 * [SWS_Os_00387]
	 * ⌈如果在调用 SyncScheduleTable()
	 * 时调度表 <ScheduleTableID> 无效
	 * 或无法显式同步调度表
	 * （ OsScheduleTblSyncStrategy不等于EXPLICIT ） ，
	 * 则 SyncScheduleTable()应返回E_OS_ID 。 ⌋ ( )
	 */
	if ((ScheduleTableID >= AUTOSAR_NR_SCHEDULE_TABLE)
		|| ((autosar_schedule_tables[ScheduleTableID].sync & EXPLICIT) != EXPLICIT)) {
		status = E_OS_ID;
		goto out;
	}

#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(app_id, TYPE_SCHEDULE_TABLE,
		&autosar_schedule_tables[ScheduleTableID].object) != ACCESS) {
		status = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_OS_APPLICATION) */

	/**
	 * [SWS_Os_00455]
	 * ⌈如果SyncScheduleTable()调用中
	 * 的 <Value>大于或等于OsScheduleTableDuration ，
	 * 则 SyncScheduleTable()应返回E_OS_VALUE 。 ⌋ ( )
	 */
	if (Value >= autosar_schedule_tables[ScheduleTableID].duration) {
		status = E_OS_VALUE;
		goto out;
	}
#endif

	/* 一定要先检查ID有效之后再上锁 */
	smp_lock_irqsave(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

	/*********************************
	 * [SWS_Os_00526]
	 * ⌈ SyncScheduleTable()的可用性：
	 * 在可扩展性类 2 和 4 中可用。⌋ ( )
	 ***********************************/

	/**
	 * [SWS_Os_00456]
	 * ⌈如果调度表 <ScheduleTableID> 的状态
	 * 在调用SyncScheduleTable()
	 * 等于SCHEDULETABLE_STOPPED
	 * 或SCHEDULETABLE_NEXT
	 * SyncScheduleTable()应返回E_OS_STATE 。 ⌋ ( )
	 */
	if ((autosar_schedule_tables[ScheduleTableID].status == SCHEDULETABLE_STOPPED)
		|| (autosar_schedule_tables[ScheduleTableID].status == SCHEDULETABLE_NEXT)) {
		status = E_OS_STATE;
		goto unlock_out;
	}

	/**
	 * [SWS_Os_00457]
	 * ⌈如果SyncScheduleTable()调用中的参数有效，
	 * 则 SyncScheduleTable()应向操作系统模块
	 * 提供给定调度表的当前同步计数。
	 * （用于将调度表的处理同步到同步计数器。） ⌋ （ )
	 */
	status = __sync_schedule_table(ScheduleTableID, Value);

unlock_out:
	smp_unlock_irqrestore(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

out:
	return status;
}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */

/*
 * 语法
 * StatusType GetScheduleTableStatus (
 *      ScheduleTableType ScheduleTableID,
 *      ScheduleTableStatusRefType ScheduleStatus
 * )
 *
 * 服务 ID [hex]
 *      0x0e
 *
 * 同步/异步
 *      同步（Synchronous）
 *
 * 可重入性
 *      可重入
 *
 * 参数 (in)
 *      ScheduleTableID
 *      请求状态的调度表
 *
 * 参数 (inout)
 *      None
 *
 * 参数 (out)
 *      ScheduleStatus
 *      ScheduleTableStatusType 的引用
 *
 * 返回值
 *      StatusType
 *      E_OK：无错误
 *      E_OS_ID（仅处于 EXTENDED 状态）：无效的 Schedule TableID
 *
 * 描述
 *      该服务查询调度表的状态（也与同步相关）。
 *
 * 引用
 *      AUTOSAR OS 8.4.16 GetScheduleTableStatus [SWS_Os_00227]
 */
FUNC(StatusType, OS_CODE) GetScheduleTableStatus(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID,
	VAR(ScheduleTableStatusRefType, AUTOMATIC) ScheduleStatus)
{
	VAR(StatusType, AUTOMATIC) status = E_OK;

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)

#if defined(EXTENDED_STATUS)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 */
	if (ScheduleTableID >= AUTOSAR_NR_SCHEDULE_TABLE) {
		status = E_OS_ID;
		goto out;
	}

	/**
	 * 在拓展模式下，检查传入的引用是否为 NULL
	 *
	 * [SWS_Os_00566]
	 * ⌈操作系统 API 应在扩展模式下检查所有指针参数
	 * 是否为NULL指针，如果此类参数为NULL ，
	 * 则以扩展状态返回E_OS_PARAM_POINTER 。 ⌋ ( )
	 */
	if (ScheduleStatus == NULL) {
		status = E_OS_PARAM_POINTER;
		goto out;
	}
#endif

	/***************************************
	 * [SWS_Os_00528]
	 * ⌈ GetScheduleTableStatus()的可用性：
	 * 可用于所有可扩展性类。 ⌋ ( )
	 ***************************************/

	/**
	 * [SWS_Os_00289]
	 * ⌈如果调用GetScheduleTableStatus ()中的
	 * 调度表 <ScheduleTableID>未启动，
	 * 则 GetScheduleTableStatus()应通过
	 * 参考参数 <ScheduleStatus>传回
	 * SCHEDULETABLE_STOPPED并返回E_OK 。 ⌋ ( )
	 *
	 * [SWS_Os_00353]
	 * ⌈如果 GetScheduleTableStatus () 调用中
	 * 的调度表 <ScheduleTableID> 在
	 * NextScheduleTable ()调用中
	 * 使用并等待当前调度表结束，
	 * GetScheduleTableStatus()应通过
	 * 参考参数 <ScheduleStatus>返回
	 * SCHEDULETABLE_NEXT AND 应返回E_OK 。 ⌋ ( )
	 *
	 * [SWS_Os_00354]
	 * ⌈如果调用GetScheduleTableStatus () 中的
	 * 调度表 <ScheduleTableID> 配置了显式同步，
	 * 并且 <ScheduleTableID> 是使用
	 * StartScheduleTableSynchron()启动的，
	 * 并且没有向操作系统提供同步计数，
	 *  GetScheduleTableStatus()将返回
	 * SCHEDULETABLE_WAITING通过参考参数
	 *  <ScheduleStatus> 并且应返回E_OK 。 ⌋ ( )
	 *
	 * [SWS_Os_00290]
	 * ⌈如果调用GetScheduleTableStatus ()中的
	 * 调度表 <ScheduleTableID>已启动且同步，
	 * 则 GetScheduleTableStatus()应通过参考参数
	 *  <ScheduleStatus>传回SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS
	 * 并返回E_OK 。 ⌋ ( )
	 *
	 * [SWS_Os_00291]
	 * ⌈如果调用GetScheduleTableStatus () 中的
	 * 调度表 <ScheduleTableID> 已启动
	 * 且不同步（偏差不在精度区间内或调度表已设置为异步），
	 * 则GetScheduleTableStatus()应通过
	 * 参考参数 ScheduleStatus 返回 SCHEDULETABLE_RUNNING
	 * 并应返回E_OK 。 ⌋ ( )
	 *
	 * [SWS_Os_00293]
	 * ⌈如果GetScheduleTableStatus ()调用中的
	 * 标识符 <ScheduleTableID>无效，
	 * 则 GetScheduleTableStatus()应返回E_OS_ID 。 ⌋ ( )
	 */
	*ScheduleStatus = autosar_schedule_tables[ScheduleTableID].status;

out:
	return status;
}


#include <autosar/internal.h>

/*
 * 语法
 * StatusType NextScheduleTable (
 *      ScheduleTableType ScheduleTableID_From,
 *      ScheduleTableType ScheduleTableID_To
 * )
 *
 * 服务 ID [hex]
 *      0x0a
 *
 * 同步/异步
 *      同步（Synchronous）
 *
 * 可重入性
 *      可重入
 *
 * 参数 (in)
 *      ScheduleTableID_From
 *      当前处理的调度表
 *
 *      ScheduleTableID_To
 *      提供其一系列到期点的调度表
 *
 * 参数 (inout)
 *      None
 *
 * 参数 (out)
 *      None
 *
 * 返回值
 *      StatusType
 *      E_OK：没有错误
 *      E_OS_ID（仅处于 EXTENDED 状态）：ScheduleTableID_From
 *                或 ScheduleTableID_To 无效
 *      E_OS_NOFUNC：ScheduleTableID_From 未启动
 *      E_OS_STATE：ScheduleTableID_To 已启动或下一个
 *
 * 描述
 *      该服务将处理从一个调度表切换到另一个调度表。
 *
 * 引用
 *      AUTOSAR OS 8.4.12 NextScheduleTable [SWS_Os_00191]
 */
FUNC(StatusType, OS_CODE) NextScheduleTable(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID_From,
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID_To)
{
	VAR(uintptr_t, AUTOMATIC) flags;
	VAR(StatusType, AUTOMATIC) status = E_OK;
	VAR(ScheduleTableType, AUTOMATIC) nextSchedtblID;

#if defined(AUTOSAR_OS_APPLICATION)
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();
#endif 

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)

#if defined(AUTOSAR_OS_APPLICATION)
	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(EXTENDED_STATUS)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 *
	 * [SWS_Os_00282]
	 * ⌈如果NextScheduleTable()调用中的
	 * 输入参数 <ScheduleTableID_From>
	 * 或 <ScheduleTableID_To>无效，
	 * 则 NextScheduleTable()应返回E_OS_ID 。 ⌋ ( )
	 */
	if ((ScheduleTableID_From >= AUTOSAR_NR_SCHEDULE_TABLE)
		|| (ScheduleTableID_To >= AUTOSAR_NR_SCHEDULE_TABLE)) {
		status = E_OS_ID;
		goto out;
	}

#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(app_id, TYPE_SCHEDULE_TABLE,
		&autosar_schedule_tables[ScheduleTableID_From].object) != ACCESS
		|| CheckObjectAccess(app_id, TYPE_SCHEDULE_TABLE,
		&autosar_schedule_tables[ScheduleTableID_To].object) != ACCESS) {
		status = E_OS_ID;
		goto out;
	}
#endif

	/**
	 *
	 * [SWS_Os_00330]
	 * ⌈如果调用NextScheduleTable()调度表
	 * <ScheduleTableID_To> 由与调度表
	 * <ScheduleTableID_From> 不同的计数器驱动，
	 * 则NextScheduleTable()将返回错误E_OS_ID 。 ⌋ ( )
	 */
	if (autosar_schedule_tables[ScheduleTableID_From].counterID
		!= autosar_schedule_tables[ScheduleTableID_To].counterID) {
		status = E_OS_ID;
		goto out;
	}

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
	/**
	 * [SWS_Os_00484]
	 * ⌈如果在NextScheduleTable ()调用中
	 *  <ScheduleTableID_To> 的OsScheduleTblSyncStrategy
	 * 不等于<ScheduleTableID_From> 的 OsScheduleTblSyncStrategy
	 * 则NextScheduleTable()应返回E_OS_ID 。 ⌋ ( )
	 */
	if ((autosar_schedule_tables[ScheduleTableID_From].sync & SYNC_MASK)
		!= (autosar_schedule_tables[ScheduleTableID_To].sync & SYNC_MASK)) {
		status = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */
#endif

	/* 一定要先检查ID有效之后再上锁 */
	if (ScheduleTableID_From < ScheduleTableID_To) {
		local_irq_save(flags);
		smp_lock(&(autosar_schedule_tables[ScheduleTableID_From].lock));
		smp_lock(&(autosar_schedule_tables[ScheduleTableID_To].lock));
	} else if (ScheduleTableID_From > ScheduleTableID_To) {
		local_irq_save(flags);
		smp_lock(&(autosar_schedule_tables[ScheduleTableID_To].lock));
		smp_lock(&(autosar_schedule_tables[ScheduleTableID_From].lock));
	} else {
		status = E_OS_ID;
		goto out;
	}

	/********************************
	 * [SWS_Os_00524]
	 * ⌈ NextScheduleTable()的可用性：
	 * 可用于所有可扩展性类。 ⌋ ( )
	 ********************************/

	/**
	 * [SWS_Os_00283]
	 * ⌈如果NextScheduleTable()调用中的
	 * 调度表 <ScheduleTableID_From>
	 * 处于SCHEDULETABLE_STOPPED状态
	 * 或处于SCHEDULETABLE_NEXT状态，
	 * 则 NextScheduleTable()应保持
	 *  <ScheduleTable_From> 和 <ScheduleTable_To>
	 * 的状态不变并返回E_OS_NOFUNC 。 ⌋ ( )
	 */
	if ((autosar_schedule_tables[ScheduleTableID_From].status == SCHEDULETABLE_STOPPED)
		|| (autosar_schedule_tables[ScheduleTableID_From].status == SCHEDULETABLE_NEXT)) {
		status = E_OS_NOFUNC;
		goto unlock_out;
	}

	/**
	 * [SWS_Os_00309]
	 * ⌈如果NextScheduleTable()调用中的
	 * 调度表 <ScheduleTableID_To>不处于
	 * 状态SCHEDULETABLE_STOPPED ，
	 * 则 NextScheduleTable()应保持
	 *  <ScheduleTable_From> 和 <ScheduleTable_To>
	 * 的状态不变并返回E_OS_STATE 。 ⌋ ( )
	 */
	if (autosar_schedule_tables[ScheduleTableID_To].status != SCHEDULETABLE_STOPPED) {
		status = E_OS_STATE;
		goto unlock_out;
	}

	/**
	 * [SWS_Os_00324]
	 * ⌈如果NextScheduleTable()的输入参数有效
	 * 并且 <ScheduleTableID_From>
	 * 已经有一个“下一个”调度表，
	 * 则NextScheduleTable()将用 <ScheduleTableID_To>
	 * 替换之前的“下一个”调度表并更改
	 * 旧的“下一个”调度表状态为SCHEDULETABLE_STOPPED 。 ⌋ ( )
	 */
	nextSchedtblID = autosar_schedule_tables[ScheduleTableID_From].next_schedtblID;
	if (nextSchedtblID < NO_NEXT_SCHEDULE_TABLE) {
		autosar_schedule_tables[nextSchedtblID].status = SCHEDULETABLE_STOPPED;
	}

	/**
	 * [SWS_Os_00284]
	 * ⌈如果NextScheduleTable()的输入参数有效，
	 * 则NextScheduleTable()应开始处理调度表
	 * <ScheduleTableID_To> <ScheduleTableID_From>.
	 * FinalDelay 在处理完 <ScheduleTableID_From> 上的
	 * 最终到期点后tick并返回E_OK 。
	 * NextScheduleTable()应在 <ScheduleTableID_From>
	 * 处处理 <ScheduleTableID_To> 上的 Initial Expiry Point。
	 * Final Delay + <ScheduleTable_To>.Initial Offset
	 * 在处理完 <ScheduleTableID_From> 上的
	 *  Final Expiry Point 之后tick作响应。 ⌋ ( )
	 */
	autosar_schedule_tables[ScheduleTableID_From].next_schedtblID = ScheduleTableID_To;
	autosar_schedule_tables[ScheduleTableID_To].status = SCHEDULETABLE_NEXT;

	/**
	 * 该需求在 <schedule_table.c>的schedule_table_callback()函数中实现
	 * [SWS_Os_00505]
	 * ⌈如果在NextScheduleTable ()调用中调度表
	 *  <ScheduleTableID_From> 和 <ScheduleTableID_To>
	 * 的OsScheduleTblSyncStrategy是EXPLICIT
	 * 并且操作系统模块已经同步 <ScheduleTableID_From>，
	 * 则 NextScheduleTable()将在处理开始后继续同步
	 *  <ScheduleTableID_To >。 ⌋ ( )
	 */

	/**
	 * 该需求在 <StopScheduleTable.c> 中实现
	 * [SWS_Os_00453]
	 * ⌈如果NextScheduleTable()调用中的
	 * < ScheduleTableID_From>停止，
	 * 则 NextScheduleTable()不应启动“下一个”调度表
	 * 并将其状态更改为SCHEDULETABLE_STOPPED 。 ⌋ ( )
	 */

unlock_out:
	smp_unlock(&(autosar_schedule_tables[ScheduleTableID_From].lock));
	smp_unlock(&(autosar_schedule_tables[ScheduleTableID_To].lock));
	local_irq_restore(flags);

out:
	return status;
}

#if defined(AUTOSAR_SYNCHRONIZATION_SUPPORT)
/*
 * 语法
 * StatusType SetScheduleTableAsync (
 *      ScheduleTableType ScheduleTableID
 * )
 *
 * 服务 ID [hex]
 *      0x0d
 *
 * 同步/异步
 *      同步（Synchronous）
 *
 * 可重入性
 *      可重入
 *
 * 参数 (in)
 *      ScheduleTableID
 *      请求切换状态的调度表ID
 *
 * 参数 (inout)
 *      None
 *
 * 参数 (out)
 *      None
 *
 * 返回值
 *      StatusType
 *      E_OK：无错误
 *      E_OS_ID（仅处于 EXTENDED 状态）：无效的 Schedule TableID
 *
 * 描述
 *      此服务停止计划表的同步。
 *
 * 引用
 *      AUTOSAR OS 8.4.15 SetScheduleTableAsync [SWS_Os_00422]
 */
FUNC(StatusType, OS_CODE) SetScheduleTableAsync(
	VAR(ScheduleTableType, AUTOMATIC) ScheduleTableID)
{
	VAR(uintptr_t, AUTOMATIC) flags;
	VAR(StatusType, AUTOMATIC) status = E_OK;

#if defined(AUTOSAR_OS_APPLICATION)
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();
#endif

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)

#if defined(AUTOSAR_OS_APPLICATION)
	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
#endif

#if defined(EXTENDED_STATUS)

	/**
	 * [SWS_Os_00458]
	 * ⌈如果 SetScheduleTableAsync () 调用中 <ScheduleTableID>
	 * 的OsScheduleTblSyncStrategy 不等于EXPLICIT
	 * 或如果 <ScheduleTableID> 无效，
	 * 则SetScheduleTableAsync () 应返回E_OS_ID 。 ⌋ ( )
	 */
	if ((ScheduleTableID >= AUTOSAR_NR_SCHEDULE_TABLE)
		|| ((autosar_schedule_tables[ScheduleTableID].sync & EXPLICIT) != EXPLICIT)) {
		status = E_OS_ID;
		goto out;
	}

#if defined(AUTOSAR_OS_APPLICATION)
	if (CheckObjectAccess(app_id, TYPE_SCHEDULE_TABLE,
		&autosar_schedule_tables[ScheduleTableID].object) != ACCESS) {
		status = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_OS_APPLICATION) */
#endif

	/* 一定要先检查ID有效之后再上锁 */
	smp_lock_irqsave(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

	/****************************************
	 * [SWS_Os_00527]
	 * ⌈ SetScheduleTableAsync()的可用性：
	 * 在可伸缩性类 2 和 4 中可用。⌋ ( )
	 ****************************************/

	/**
	 * [SWS_Os_00483]
	 * ⌈如果在SetScheduleTableAsync() 调用中
	 *  <ScheduleTableID> 的当前状态等于
	 * SCHEDULETABLE_STOPPED、 SCHEDULETABLE_NEXT
	 * 或	SCHEDULETABLE_WAITING
	 * 然后SetScheduleTableAsync()应返回E_OS_STATE 。 ⌋ ( )
	 */
	if ((autosar_schedule_tables[ScheduleTableID].status == SCHEDULETABLE_STOPPED)
		|| (autosar_schedule_tables[ScheduleTableID].status == SCHEDULETABLE_NEXT)
		|| (autosar_schedule_tables[ScheduleTableID].status == SCHEDULETABLE_WAITING)) {
		status = E_OS_STATE;
		goto unlock_out;
	}

	/**
	 * [SWS_Os_00300]
	 * ⌈如果在SetScheduleTableAsync ()调用中
	 *  <ScheduleTableID> 的当前状态等于
	 * SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS
	 * （或SCHEDULETABLE_RUNNING） ，
	 * 则SetScheduleTableAsync()应设置
	 * （或在SCHEDULETABLE_RUNNING的情况下保持）
	 * <ScheduleTableID>的状态为
	 * SCHEDULETABLE_RUNNING ⌋ ( )
	 */
	autosar_schedule_tables[ScheduleTableID].status = SCHEDULETABLE_RUNNING;

	/**
	 * [SWS_Os_00362]
	 * ⌈如果为正在运行的调度表调用SetScheduleTableAsync ()，
	 * 操作系统模块将停止进一步同步，
	 * 直到调用SyncScheduleTable ()。 ⌋ ( )
	 *
	 * [SWS_Os_00323]
	 * ⌈如果为正在运行的调度表调用SetScheduleTableAsync ()，
	 * 则操作系统模块应继续处理调度表上的到期点。 ⌋ ( )
	 */
	autosar_schedule_tables[ScheduleTableID].sync = EXPLICIT_ASYNC;
	autosar_schedule_tables[ScheduleTableID].waiter.cycle
		= __offset_next_2_expiry_point(&(autosar_schedule_tables[ScheduleTableID]));

unlock_out:
	smp_unlock_irqrestore(&(autosar_schedule_tables[ScheduleTableID].lock), flags);

out:
	return status;
}
#endif /* defined(AUTOSAR_SYNCHRONIZATION_SUPPORT) */
